package com.skyworth.ui.newrecycleview;

import android.content.Context;
import android.graphics.Rect;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;

import com.skyworth.util.Util;

public class NewLayoutManager extends GridLayoutManager
{
    private static final int EXTRA_SPACE = Util.Div(540);

    private boolean isMiddleScroll = false;

    private int mUpOrLeftScrollOffset = 0, mDownOrRightScrollOffset;

    public NewLayoutManager(Context context, int spanCount)
    {
        super(context, spanCount);
    }

    public NewLayoutManager(Context context, int spanCount, int orientation)
    {
        this(context, spanCount);
        setOrientation(orientation);
    }

    public void setMiddleScroll(boolean middleScroll)
    {
        isMiddleScroll = middleScroll;
    }

    public void setScorllOfset(int upOrLeftOffset, int downOrRightOffset)
    {
        mUpOrLeftScrollOffset = upOrLeftOffset;
        mDownOrRightScrollOffset = downOrRightOffset;
    }

    @Override
    protected int getExtraLayoutSpace(RecyclerView.State state)
    {
        return EXTRA_SPACE;
    }

    @Override
    public View onFocusSearchFailed(View focused, int focusDirection, RecyclerView.Recycler recycler,
                                    RecyclerView.State state)
    {
        if(getSpanCount() == 1) {
            return super.onFocusSearchFailed(focused, focusDirection, recycler, state);
        }

        View nextFocus = super.onFocusSearchFailed(focused, focusDirection, recycler, state);
        if (nextFocus == null)
        {
            return null;
        }

        /**
         * 获取当前焦点的位置
         */
        int fromPos = getPosition(focused);
        /**
         * 获取我们希望的下一个焦点的位置
         */
        int nextPos = getNextViewPos(fromPos, focusDirection);
        nextFocus = findViewByPosition(nextPos);
        Log.v("lgx", "fromPos---> " + fromPos + "  nextPos---> " + nextPos + "  nextFocus --> " + nextFocus);

        return nextFocus;
    }

    public int getNextViewPos(int fromPos, int direction)
    {
        int offset = calcOffsetToNextView(direction);

        if (hitBorder(fromPos, offset))
        {
            return fromPos;
        }

        return fromPos + offset;
    }

    protected int calcOffsetToNextView(int direction)
    {
        int spanCount = getSpanCount();
        int orientation = getOrientation();

        if (orientation == VERTICAL)
        {
            switch (direction)
            {
                case View.FOCUS_DOWN:
                    return spanCount;
                case View.FOCUS_UP:
                    return -spanCount;
                case View.FOCUS_RIGHT:
                    return 1;
                case View.FOCUS_LEFT:
                    return -1;
            }
        } else if (orientation == HORIZONTAL)
        {
            switch (direction)
            {
                case View.FOCUS_DOWN:
                    return 1;
                case View.FOCUS_UP:
                    return -1;
                case View.FOCUS_RIGHT:
                    return spanCount;
                case View.FOCUS_LEFT:
                    return -spanCount;
            }
        }

        return 0;
    }

    private boolean hitBorder(int from, int offset)
    {
        int spanCount = getSpanCount();

        if (Math.abs(offset) == 1)
        {
            int spanIndex = from % spanCount;
            int newSpanIndex = spanIndex + offset;
            return newSpanIndex < 0 || newSpanIndex >= spanCount;
        } else
        {
            int newPos = from + offset;
            return newPos < 0 && newPos >= spanCount;
        }
    }

    @Override
    public boolean requestChildRectangleOnScreen(RecyclerView parent, View child, Rect rect,
                                                 boolean immediate)
    {
        int parentLeft = getPaddingLeft();
        int parentTop = getPaddingTop();
        int parentRight = getWidth() - getPaddingRight();
        int parentBottom = getHeight() - getPaddingBottom();
        int childLeft = child.getLeft() + rect.left;
        int childTop = child.getTop() + rect.top;
        int childRight = childLeft + rect.width();
        int childBottom = childTop + rect.height();

        if (isMiddleScroll)
        {
            parentLeft = getPaddingLeft() + getWidth() / 2;
            parentTop = getPaddingTop() + getHeight() / 2;
            parentRight = getWidth() / 2 - getPaddingRight();
            parentBottom = getHeight() / 2 - getPaddingBottom();
            childLeft = child.getLeft() + rect.left - child.getScrollX() + rect.width() / 2;
            childTop = child.getTop() + rect.top - child.getScrollY() + rect.height() / 2;
            childRight = childLeft;// + rect.width();
            childBottom = childTop;// + rect.height();
        }

        final int offScreenLeft = Math.min(0, childLeft - parentLeft);
        final int offScreenTop = Math.min(0, childTop - parentTop);
        final int offScreenRight = Math.max(0, childRight - parentRight);
        final int offScreenBottom = Math.max(0, childBottom - parentBottom);

        int dx = 0;
        if (getOrientation() == OrientationHelper.HORIZONTAL)
//            if (isMiddleScroll)
//                dx = offScreenLeft != 0 ? offScreenLeft : (childLeft - parentLeft);
//            else
            dx = offScreenLeft != 0 ? offScreenLeft : Math.min(childLeft - parentLeft, offScreenRight);

        int dy = 0;
        if (getOrientation() == OrientationHelper.VERTICAL)
//            if (isMiddleScroll)
//                dy = offScreenTop != 0 ? offScreenTop : (childTop - parentTop);
//            else
            dy = offScreenTop != 0 ? offScreenTop : Math.min(childTop - parentTop, offScreenBottom);

        if (dx != 0 || dy != 0)
        {
            if (getOrientation() == OrientationHelper.HORIZONTAL)// && !isMiddleScroll)
            {
                if (dx < 0)
                {
                    dx -= mUpOrLeftScrollOffset;
                } else
                {
                    dx += mDownOrRightScrollOffset;
                }
            } else if (getOrientation() == OrientationHelper.VERTICAL)// && !isMiddleScroll)
            {
                if (dy < 0)
                {
                    dy -= mUpOrLeftScrollOffset;
                } else
                {
                    dy += mDownOrRightScrollOffset;
                }
            }
            if (immediate)
            {
                parent.scrollBy(dx, dy);
            } else
            {
                parent.smoothScrollBy(dx, dy);
            }
            return true;
        }
        return false;
    }
}
